﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_GL_OBJECT_MANAGER_H
#define _UXS_GL_OBJECT_MANAGER_H

#pragma once

#include "GLCommon.h"

namespace UX_STL
{
namespace GLShell
{

	//
	// GL Object Manager
	//

	class UX_EXPORT GLObjectManager : public GLBaseObject
	{
#ifdef UX_GL_USE_VAO
	private:
		typedef array< GLuint, TFastCopyStrategy< GLuint > >	vao_array_t;

		typedef bool (GLObjectManager:: *PReallocVAOsProc_t)(uint);
		typedef bool (GLObjectManager:: *PDeleteVAOsProc_t)();
		typedef bool (GLObjectManager:: *PSetAttribsProc_t)(GLuint, const uni_array<const GLVertexAttribExt> &);

		PReallocVAOsProc_t		_pReallocVAOs;
		PDeleteVAOsProc_t		_pDeleteVAOs;
		PSetAttribsProc_t		_pSetAttribs;

		Mutex		_sCSLockVAO;
		vao_array_t				_aAllVAOs,
								_aFreeVAOs;

		static const uint		_s_uMinVAOSize;

		
	private:
		bool _ReallocVAOs(uint uCount);

		bool _MTReallocVAOs(uint);
		bool _MTDeleteVAOs();
		bool _MTSetAttribs(GLuint, const uni_array<const GLVertexAttribExt> &);
		
		bool _STReallocVAOs(uint);
		bool _STDeleteVAOs();
		bool _STSetAttribs(GLuint, const uni_array<const GLVertexAttribExt> &);

	public:
		bool GenVertexArrays(GLsizei n, GLuint * arrays);
		bool DeleteVertexArrays(GLsizei n, const GLuint * arrays);

		bool SetAttribs(GLuint uVAO, const uni_array<const GLVertexAttribExt> &aAttribs);

		static bool s_GetAttribs(GLuint uVAO, GLVerticesAttribsExt_t &aAttribs);
		static bool s_SetAttribs(GLuint uVAO, const uni_array<const GLVertexAttribExt> &aAttribs);
#endif	// UX_GL_USE_VAO

	private:
		void _CheckNotReleasedObjects();

	public:
		GLObjectManager();
		~GLObjectManager();
		
		bool Init(uint uNumVAO, bool bMT = false);
		void Destroy();

		bool GenBuffers(GLsizei n, GLuint * buffers) const;
		bool GenFramebuffers(GLsizei n, GLuint * ids) const;
		bool GenProgramPipelines(GLsizei n, GLuint * pipelines) const;
		bool GenQueries(GLsizei n, GLuint * ids) const;
		bool GenRenderbuffers(GLsizei n, GLuint * renderbuffers) const;
		bool GenSamplers(GLsizei n, GLuint * samplers) const;
		bool GenTransformFeedbacks(GLsizei n, GLuint * ids) const;
		bool GenTextures(GLsizei n, GLuint * textures) const;
		bool CreateShaders(GLsizei n, const GLenum *shaderTypes, GLuint * ids) const;
		bool CreateShader(GLenum shaderType, GLuint &shader) const;
		bool CreateProgram(GLuint &program) const;
		bool FenceSync(GLenum condition, GLbitfield flags, GLsync &sync) const;

		bool DeleteBuffers(GLsizei n, const GLuint * buffers) const;
		bool DeleteFramebuffers(GLsizei n, const GLuint * ids) const;
		bool DeleteProgramPipelines(GLsizei n, const GLuint * pipelines) const;
		bool DeleteQueries(GLsizei n, const GLuint * ids) const;
		bool DeleteRenderbuffers(GLsizei n, const GLuint * renderbuffers) const;
		bool DeleteSamplers(GLsizei n, const GLuint * samplers) const;
		bool DeleteTransformFeedbacks(GLsizei n, const GLuint * ids) const;
		bool DeleteTextures(GLsizei n, const GLuint * textures) const;
		bool DeleteShaders(GLsizei n, const GLuint * ids) const;
		bool DeleteShader(GLuint shader) const;
		bool DeleteProgram(GLuint program) const;
		bool DeleteSync(GLsync sync) const;
	};

	
	
#ifdef UX_GL_USE_VAO
/*
=================================================
	устанавливает атрибуты VAO для всех контекстов
=================================================
*/
	inline bool GLObjectManager::SetAttribs(GLuint uVAO, const uni_array<const GLVertexAttribExt> &aAttribs)
	{
		return (this->*_pSetAttribs)( uVAO, aAttribs );
	}

#endif	// UX_GL_USE_VAO

//-------------------------------------------------------------------
	
}	// GLShell
}	// UX_STL

#endif	// _UXS_GL_OBJECT_MANAGER_H